package ru.amse.ilyin.analyzer.impl;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import ru.amse.ilyin.analyzer.AnalyzerException;
import ru.amse.ilyin.analyzer.Class;
import ru.amse.ilyin.analyzer.Interface;
import ru.amse.ilyin.analyzer.Package;
import ru.amse.ilyin.parser.ClassFileParser;

/**
 * Implementation of {@link Package} interface.
 *
 * @author Alexander Ilyin
 */
public class PackageImpl implements Package {
	private final String name;
	
	private final File path;
	
	private final Set<Package> importedPackages = new HashSet<Package>();
	
	private Set<Class> classes;
	
	private Set<Interface> interfaces;
	
	/**
	 * Creates new instance of <code>PackageImpl</code> class.
	 * 
	 * @param path package pathname
	 * @param name package name
	 */
	public PackageImpl(File path, String name) {
		this.name = name;
		this.path = path;
	}
	
	public String getName() {
		return name;
	}
	
	public Set<Package> getImportedPackages() throws AnalyzerException {
		return importedPackages;
	}
	
	public Set<Class> getClasses() throws AnalyzerException {
		parseContent();
		
		return classes;
	}
	
	public Set<Interface> getInterfaces() throws AnalyzerException {
		parseContent();
		
		return interfaces;
	}
	
	private void parseContent() {
		if (classes != null) {	// already parsed
			return ;
		}
		
		classes = new HashSet<Class>();
		interfaces = new HashSet<Interface>();
		
		for (File filename : path.listFiles(new ClassFileFilter())) {
			try {
				final ClassFileParser parser = new ClassFileParser(filename);
				parser.parse();
				if (parser.isClass()) {
                    final ClassImpl aClass = new ClassImpl(parser.getName());
                    aClass.setSuperclass(parser.getSuperclass());
                    aClass.setSuperinterfaces(parser.getSuperinterfaces());
					classes.add(aClass);
				} else {
					final InterfaceImpl anIinterface = 
                            new InterfaceImpl(parser.getName());
                    anIinterface.setSuperinterfaces(parser.getSuperinterfaces());
                    interfaces.add(anIinterface);
				}
			} catch(IOException e) {
				//TODO replace with logger
				System.out.println("failed to parse a file: " + filename);
				System.out.println(e.getMessage());
			}
		}
	}
	
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof PackageImpl)) {
			return false;
		}
		
		final PackageImpl p = (PackageImpl) o;
		return name.equals(p.getName());
	}
	
	@Override
	public int hashCode() {
		return name.hashCode();
	}
	
	@Override
	public String toString() {
		return name;
	}
}
